package com.lidx.back.statistics.websocket;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.lidx.back.statistics.entity.SysUser;
import com.lidx.back.statistics.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by chen on 2017/2/23.
 */
@Component
public class MyWebSocketHandler implements WebSocketHandler {

    @Autowired
    private ISysUserService sysUserService;

    //用于保存HttpSession与WebSocketSession的映射关系
    public static final Map<Integer, WebSocketSession> userSocketSessionMap;

    static {
        userSocketSessionMap = new ConcurrentHashMap<Integer, WebSocketSession>();
    }

    @Override
    /**
     * 建立连接后,把登录用户的id写入WebSocketSession
     */
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        Integer uid = (Integer) webSocketSession.getAttributes().get("uid");
        SysUser user =sysUserService.getUserById(uid);
        if (userSocketSessionMap.get(uid) == null) {
            userSocketSessionMap.put(uid, webSocketSession);
            Message msg = new Message();
            msg.setFrom(0);//0表示上线消息
            msg.setText(user.getName());
            this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
        }
    }
    /**
     * 消息处理，在客户端通过Websocket API发送的消息会经过这里，然后进行相应的处理
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        if(webSocketMessage.getPayloadLength() == 0)
            return;
        Message message = new Gson().fromJson(webSocketMessage.getPayload().toString(),Message.class);
        message.setDate(new Date());
        sendMessageToUser(message.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(message)));
    }
    /**
     * 给某个用户发送消息
     *
     * @param to
     * @param textMessage
     * @throws IOException
     */
    private void sendMessageToUser(int to, TextMessage textMessage) throws IOException {
        WebSocketSession session = userSocketSessionMap.get(to);
        if (session != null && session.isOpen()){
            session.sendMessage(textMessage);
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        Iterator<Map.Entry<Integer, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        // 移除当前抛出异常用户的Socket会话
        while (it.hasNext()) {
            Map.Entry<Integer, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                String username=sysUserService.getUserById(entry.getKey()).getName();
                Message msg = new Message();
                msg.setFrom(-2);
                msg.setText(username);
                this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
                break;
            }
        }
    }

    /**
     * 关闭连接后
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        System.out.println("Websocket:" + session.getId() + "已经关闭");
        Iterator<Map.Entry<Integer, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        // 移除当前用户的Socket会话
        while (it.hasNext()) {
            Map.Entry<Integer, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                String username=sysUserService.getUserById(entry.getKey()).getName();
                Message msg = new Message();
                msg.setFrom(-2);//下线消息，用-2表示
                msg.setText(username);
                this.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
                break;
            }
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 给所有在线用户发送消息
     * @param message
     * @throws IOException
     */
    public void broadcast(final TextMessage message) throws IOException {
        Iterator<Map.Entry<Integer, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();

        //多线程群发
        while (it.hasNext()) {

            final Map.Entry<Integer, WebSocketSession> entry = it.next();

            if (entry.getValue().isOpen()) {
                // entry.getValue().sendMessage(message);
                new Thread(new Runnable() {

                    public void run() {
                        try {
                            if (entry.getValue().isOpen()) {
                                entry.getValue().sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }).start();
            }

        }
    }
}
